package com.mida.dms.knw.service.impl;

import com.mida.dms.knw.Result.BaseResult;
import com.mida.dms.knw.entity.KnwConceptualDetail;
import com.mida.dms.knw.entity.KnwIndividualRelation;
import com.mida.dms.knw.entity.vo.*;
import com.mida.dms.knw.mapper.KnwConceptualDetailMapper;
import com.mida.dms.knw.mapper.KnwConceptualMapper;
import com.mida.dms.knw.mapper.KnwIndividualMapper;
import com.mida.dms.knw.mapper.KnwIndividualRelationMapper;
import com.mida.dms.knw.service.KnwIndividualRelationService;
import com.mida.dms.knw.service.SoidService;
import com.mida.dms.knw.vo.KnwIndividualRelationPageVo;
import com.mida.dms.knw.vo.Page;
import com.mida.dms.knw.vo.PageResultVo;
import com.mida.dms.knw.vo.PullDownMenuVO;
import com.mida.tool.common.result.ActionResult;
import com.mida.tool.common.result.ListResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <h1>实例关系服务实现</h1>
 * <p>
 *
 * </p>
 *
 * @author jian.li on 2021/7/15 15:05
 */
@Service
@Slf4j
public class KnwIndividualRelationServiceImpl extends BaseResult implements KnwIndividualRelationService {

    @Autowired
    private SoidService soidService;

    @Autowired
    private KnwIndividualRelationMapper knwIndividualRelationMapper;

    @Autowired
    private KnwIndividualMapper knwIndividualMapper;

    @Autowired
    private KnwConceptualDetailMapper knwConceptualDetailMapper;

    @Autowired
    private KnwConceptualMapper knwConceptualMapper;


    /**
     * 新增实例关系
     * <p>
     * 实例是否启用在实例下拉的时候就做筛选
     *
     * @param relation
     * @return
     */
    @Override
    @Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
    public ActionResult addSingle(KnwIndividualRelationVo relation) {
        log.info("开始新增实例关系");
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        try {
            if (ObjectUtils.isEmpty(relation.getSourceIndividualSoid())) {
                buildBadRequestActionWarn(actionResult, "源实例不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getTargetIndividualSoid())) {
                buildBadRequestActionWarn(actionResult, "目标实例不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getConceptualSoid())) {
                buildBadRequestActionWarn(actionResult, "关系名称不能为空");
                return actionResult;
            }

            if (relation.getSourceIndividualSoid().compareTo(relation.getTargetIndividualSoid()) == 0) {
                buildBadRequestActionWarn(actionResult, "源实例和目标实例不可相同");
                return actionResult;
            }

            // 关系查重
            int count = knwIndividualRelationMapper.selectDistinct(relation.getSourceIndividualSoid(), relation.getTargetIndividualSoid(), relation.getConceptualSoid());
            if (count > 0) {
                buildBadRequestActionWarn(actionResult, "实例关系已存在: " +
                        "源实例: " + relation.getSourceIndividualName() +
                        ",目标实例: " + relation.getTargetIndividualName() +
                        ",实例关系名称soid(ConceptualSoid): " + relation.getConceptualSoid());
                return actionResult;
            }

            // 新增实例关系
            Long soid = soidService.getSoid();
            relation.setIndividualRelationSoid(soid);
            relation.setCreateDate(new Date());
            relation.setUpdateDate(new Date());
            relation.setIsDelete(0L);
            relation.setStatus(145L);
            relation.setConceptualSoid(relation.getConceptualSoid());

            KnwIndividualRelation target = new KnwIndividualRelation();
            BeanUtils.copyProperties(relation, target);
            knwIndividualRelationMapper.insert(target);

            // 国标
            soidService.insertOid(soid, 1);
            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("新增实例关系发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(actionResult, "新增实例关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次新增实例关系耗时: " + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    /**
     * 编辑实例关系
     *
     * @param relation
     * @return
     */
    @Override
    @Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
    public ActionResult updateSingle(KnwIndividualRelationVo relation) {
        log.info("开始编辑实例关系");
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        try {
            if (ObjectUtils.isEmpty(relation.getIndividualRelationSoid())) {
                buildBadRequestActionWarn(actionResult, "实例关系soid不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getSourceIndividualSoid())) {
                buildBadRequestActionWarn(actionResult, "源实例不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getTargetIndividualSoid())) {
                buildBadRequestActionWarn(actionResult, "目标实例不能为空");
                return actionResult;
            }

            if (ObjectUtils.isEmpty(relation.getConceptualSoid())) {
                buildBadRequestActionWarn(actionResult, "关系名称不能为空");
                return actionResult;
            }

            if (relation.getSourceIndividualSoid().compareTo(relation.getTargetIndividualSoid()) == 0) {
                buildBadRequestActionWarn(actionResult, "源实例和目标实例不可相同");
                return actionResult;
            }

            // 关系查重(报告已修改的前提)
            KnwIndividualRelationVo knwIndividualRelationVo = knwIndividualRelationMapper.selectByPrimaryKey(relation.getIndividualRelationSoid());
            if (knwIndividualRelationVo != null) {
                if (knwIndividualRelationVo.getSourceIndividualSoid() != null && knwIndividualRelationVo.getTargetIndividualSoid() != null && knwIndividualRelationVo.getConceptualSoid() != null) {
                    if (knwIndividualRelationVo.getSourceIndividualSoid().longValue() != relation.getSourceIndividualSoid().longValue() ||
                            knwIndividualRelationVo.getTargetIndividualSoid().longValue() != relation.getTargetIndividualSoid().longValue() ||
                            knwIndividualRelationVo.getConceptualSoid().longValue() != relation.getConceptualSoid().longValue()) {
                        int count = knwIndividualRelationMapper.selectDistinct(relation.getSourceIndividualSoid(), relation.getTargetIndividualSoid(), relation.getConceptualSoid());
                        if (count > 0) {
                            buildBadRequestActionWarn(actionResult, "实例关系已存在: " +
                                    "源实例: " + relation.getSourceIndividualName() +
                                    ",目标实例: " + relation.getTargetIndividualName() +
                                    ",实例关系名称soid(ConceptualSoid): " + relation.getConceptualSoid());
                            return actionResult;
                        }
                    }
                }
            }

            KnwIndividualRelation target = new KnwIndividualRelation();
            BeanUtils.copyProperties(relation, target);
            knwIndividualRelationMapper.updateByPrimaryKeySelective(target);
            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("编辑实例关系发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(actionResult, "编辑实例关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次编辑实例关系耗时: " + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    @Override
    @Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
    public ActionResult delete(Long individualRelationSoid) {
        log.info("开始删除实例关系");
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        try {
            if (ObjectUtils.isEmpty(individualRelationSoid)) {
                buildBadRequestActionWarn(actionResult, "实例关系soid不能为空");
                return actionResult;
            }
            knwIndividualRelationMapper.deleteByPrimaryKey(individualRelationSoid);
            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("删除实例关系发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(actionResult, "删除实例关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次删除实例关系耗时: " + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    /**
     * 批量新增实例关系
     *
     * @param relationList
     * @return
     */
    @Override
    @Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
    public ActionResult addList(List<KnwIndividualRelationVo> relationList) {
        log.info("开始批量新增实例关系");
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        List<Long> targetIndividualSoidList = new ArrayList<>();
        try {
            if (CollectionUtils.isNotEmpty(relationList)) {
                for (KnwIndividualRelationVo relation : relationList) {
                    if (ObjectUtils.isEmpty(relation.getSourceIndividualSoid())) {
                        buildBadRequestActionWarn(actionResult, "源实例不能为空");
                        return actionResult;
                    }

                    if (ObjectUtils.isEmpty(relation.getTargetIndividualSoid())) {
                        buildBadRequestActionWarn(actionResult, "目标实例不能为空");
                        return actionResult;
                    }

                    if (ObjectUtils.isEmpty(relation.getConceptualSoid())) {
                        buildBadRequestActionWarn(actionResult, "关系名称不能为空");
                        return actionResult;
                    }

                    if (relation.getSourceIndividualSoid().compareTo(relation.getTargetIndividualSoid()) == 0) {
                        buildBadRequestActionWarn(actionResult, "源实例和目标实例不可相同");
                        return actionResult;
                    }
                    targetIndividualSoidList.add(relation.getTargetIndividualSoid());
                }
            } else {
                buildBadRequestActionWarn(actionResult, "实例关系不能为空");
                return actionResult;
            }

            KnwIndividualRelationVo knwIndividualRelationVo = relationList.get(0);
            // 关系查重
            List<KnwIndividualRelation> knwIndividualRelations = knwIndividualRelationMapper.selectListDistinct(knwIndividualRelationVo.getSourceIndividualSoid(), targetIndividualSoidList, knwIndividualRelationVo.getConceptualSoid());
            if (CollectionUtils.isNotEmpty(knwIndividualRelations)) {
                List<Long> collect = knwIndividualRelations.stream().map(e -> e.getTargetIndividualSoid()).collect(Collectors.toList());
                List<String> list = knwIndividualMapper.selectIndividualNameList(collect);
                String distinct = StringUtils.join(list, ",");
                buildBadRequestActionWarn(actionResult, "实例关系已经存在,对应目标实例 :" + distinct);
                return actionResult;
            }

            // 新增
            for (KnwIndividualRelationVo relation : relationList) {
                // 新增实例关系
                Long soid = soidService.getSoid();
                relation.setIndividualRelationSoid(soid);
                relation.setCreateDate(new Date());
                relation.setUpdateDate(new Date());
                relation.setIsDelete(0L);
                relation.setStatus(145L);
                relation.setConceptualSoid(relation.getConceptualSoid());
                KnwIndividualRelation target = new KnwIndividualRelation();
                BeanUtils.copyProperties(relation, target);
                knwIndividualRelationMapper.insert(target);

                // 国标
                soidService.insertOid(soid, 1);
            }
            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("批量新增实例关系发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(actionResult, "批量新增实例关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次批量新增实例关系耗时: " + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    /**
     * 源实例目标实例下拉
     *
     * @param page
     * @return
     */
    @Override
    public ListResult<List<KnwIndividualVo>> findSourceAndTarget(MapperPage page) {
        log.info("开始源实例目标实例下拉");
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult listResult = new ListResult();
        try {
            List<KnwIndividualVo> knwIndividualVos = knwIndividualMapper.selectIndividualNames(page);
            if (CollectionUtils.isNotEmpty(knwIndividualVos)) {
                buildListSuccess(listResult, knwIndividualVos);
            } else {
                buildListSuccess(listResult, new ArrayList<>(0));
            }
        } catch (Exception e) {
            log.error("源实例目标实例下拉发送异常", e);
            buildListWarn(listResult, "源实例目标实例下拉失败");
        } finally {
            stopWatch.stop();
            log.info("本次源实例目标实例下拉耗时: " + stopWatch.getTime() + "ms");
        }
        return listResult;
    }

    /**
     * 分页查询实例关系
     *
     * @param vo
     * @return
     */
    @Override
    public ListResult<PageResultVo<KnwIndividualRelationVo>> findPage(KnwIndividualRelationPageVo vo) {
        log.info("开始分页查询实例关系");
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult listResult = new ListResult();
        PageResultVo pageResultVo = new PageResultVo();
        Page page = new Page(vo.getCurrentPage(), vo.getPageSize());
        pageResultVo.setPage(page);
        List<KnwIndividualRelationVo> list = null;
        try {
            KnwIndividualRelationPage npage = new KnwIndividualRelationPage(vo.getCurrentPage(), vo.getPageSize(), vo.getSearchData());
            int pageCount = knwIndividualRelationMapper.findPageCount(npage);
            if (pageCount > 0) {
                page.setTotalCount(pageCount);
                list = knwIndividualRelationMapper.findRelationPage(npage);
            } else {
                page.setTotalCount(pageCount);
                list = new ArrayList<>(0);
            }
            pageResultVo.setList(list);
            buildListSuccess(listResult, pageResultVo);
        } catch (Exception e) {
            list = new ArrayList<>(0);
            pageResultVo.setList(list);
            log.error("分页查询实例关系发送异常", e);
            buildListWarn(listResult, "分页查询实例关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次分页查询实例关系耗时: " + stopWatch.getTime() + "ms");
        }
        return listResult;
    }

    /**
     * 根据实例关系soid查询实例关系
     *
     * @param individualRelationSoid
     * @return
     */
    @Override
    public ListResult<KnwIndividualRelationVo> findSingle(Long individualRelationSoid) {
        log.info("开始查询实例关系");
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult listResult = new ListResult();
        try {
            KnwIndividualRelation knwIndividualRelation = knwIndividualRelationMapper.selectByPrimaryKey(individualRelationSoid);
            if (ObjectUtils.isNotEmpty(knwIndividualRelation)) {
                buildListSuccess(listResult, knwIndividualRelation);
            } else {
                buildListSuccess(listResult, null);
            }
        } catch (Exception e) {
            log.error("根据实例关系soid查询实例关系发送异常");
            buildListWarn(listResult, "根据实例关系soid查询实例关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次根据实例关系soid查询实例关系耗时: " + stopWatch.getTime() + "ms");
        }
        return listResult;
    }

    /**
     * 启用(停用)实例关系
     *
     * @param soid
     * @return
     */
    @Override
    @Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
    public ActionResult enable(Long soid) {
        log.info("开始启用(停用)实例关系");
        StopWatch stopWatch = StopWatch.createStarted();
        ActionResult actionResult = new ActionResult();
        try {
            KnwIndividualRelation knwIndividualRelation = knwIndividualRelationMapper.selectByPrimaryKey(soid);
            if (knwIndividualRelation == null) {
                buildBadRequestActionWarn(actionResult, "实例关系不存在");
                return actionResult;
            }
            if (knwIndividualRelation.getStatus() == 146L) {
                knwIndividualRelation.setStatus(145L);
                knwIndividualRelationMapper.updateByPrimaryKeySelective(knwIndividualRelation);
            } else if (knwIndividualRelation.getStatus() == 145L) {
                knwIndividualRelation.setStatus(146L);
                knwIndividualRelationMapper.updateByPrimaryKeySelective(knwIndividualRelation);
            }
            buildActionSuccess(actionResult);
        } catch (Exception e) {
            log.error("启用(停用)实例关系发送异常", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            buildActionWarn(actionResult, "启用实例关系失败");
        } finally {
            stopWatch.stop();
            log.info("本次启用(停用)实例关系耗时: " + stopWatch.getTime() + "ms");
        }
        return actionResult;
    }

    /**
     * 实例关系下拉
     *
     * @param searchData
     * @return
     */
    @Override
    public ListResult<Object> findRelation(String searchData) {
        log.info("开始实例关系下拉");
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult listResult = new ListResult();
        List<PullDownMenuVO> targetList;
        try {
            HashMap<String, Object> map = new HashMap<>();
            if (StringUtils.isNotEmpty(searchData)) {
                map.put("searChData", searchData.trim().toUpperCase());
            }
            List<KnwConceptualVo> list = knwConceptualMapper.findAll(map);
            if (CollectionUtils.isNotEmpty(list)) {
                targetList = list.stream()
                        .filter(Objects::nonNull)
                        .map(detail -> new PullDownMenuVO(detail.getConceptualSoid(), detail.getConceptualDetailName(), null))
                        .collect(Collectors.toList());
            } else {
                targetList = new ArrayList<>(0);
            }

            buildListSuccess(listResult, targetList);
        } catch (Exception e) {
            log.error("实例关系下拉发送异常", e);
            buildListWarn(listResult, "实例关系下拉失败");
        } finally {
            stopWatch.stop();
            log.info("本次实例关系下拉耗时: " + stopWatch.getTime() + "ms");
        }
        return listResult;
    }
}
